#ifndef CPP_BASE_LRUCACHE_H_
#define CPP_BASE_LRUCACHE_H_

#include <stdint.h>
#include <unordered_map>
#include <list>
#include <functional>
#include <vector>
#include <mutex>

// 定义针对 std::pair<int64_t, int64_t> 的哈希函数结构体
struct Hash_i64_i64_Pair {
    size_t operator()(const std::pair<int64_t, int64_t>& pr) const {
        return std::abs(pr.first * 10 + pr.second);
    }
};

// 淘汰策略枚举
enum class EN_ELIMINATE_POLICY {
    EP_THROW_DIRECT,    // 直接丢弃被淘汰的数据
    EP_PENDING_DISPOSAL // 将被淘汰的数据放入待处理区
};

// 模板类 LRUCache，实现 LRU 缓存功能
template<typename KEY, typename VALUE, size_t MAXSIZE = 0, typename HASH = std::hash<KEY>>
class LRUCache {
public:
    explicit LRUCache(EN_ELIMINATE_POLICY policy = EN_ELIMINATE_POLICY::EP_PENDING_DISPOSAL) : policy_(policy) {}

    // 插入键值对到缓存中
    void setKey(const KEY& key, const VALUE& data) {
        std::lock_guard<std::mutex> guard(mutex_);
        auto it = posInfo_.find(key);
        if (it!= posInfo_.end()) {
            // 键已存在，先删除旧值
            values_.erase(it->second);
            posInfo_.erase(it);
        } else if (MAXSIZE > 0 && posInfo_.size() >= MAXSIZE) {
            // 缓存已满，根据淘汰策略处理被淘汰的值
            handleEviction();
        }
        // 将新值插入到缓存列表头部，并更新键到迭代器的映射
        values_.push_front(data);
        posInfo_[key] = values_.begin();
    }

    // 根据键获取值
    bool getKey(const KEY& key, VALUE& data) {
        std::lock_guard<std::mutex> guard(mutex_);
        auto it = posInfo_.find(key);
        if (it == posInfo_.end()) {
            return false;
        }
        // 将对应的值移动到缓存列表头部，并更新键到迭代器的映射
        moveToFront(it);
        data = *(it->second);
        return true;
    }

    // 检查键是否存在于缓存中
    bool existKey(const KEY& key) {
        std::lock_guard<std::mutex> guard(mutex_);
        return posInfo_.find(key)!= posInfo_.end();
    }

    // 根据键删除值
    void delKey(const KEY& key) {
        std::lock_guard<std::mutex> guard(mutex_);
        auto it = posInfo_.find(key);
        if (it == posInfo_.end()) {
            return;
        }
        // 删除对应的值
        values_.erase(it->second);
        posInfo_.erase(it);
    }

    // 根据给定函数进行淘汰处理
    void eliminate(std::function<bool(const VALUE&)> func, std::vector<VALUE>* _return = nullptr) {
        std::lock_guard<std::mutex> guard(mutex_);
        if (_return) {
            // 将被淘汰的值存储在 _return 指向的向量中，并返回
            std::swap(*_return, elimiValues_);
        } else {
            // 清空存储被淘汰值的向量
            elimiValues_.clear();
        }

        while (!values_.empty()) {
            VALUE last = values_.back();
            if (!func(last)) {
                break;
            }
            // 根据淘汰条件逐个淘汰缓存中的值
            KEY key = getKeyFromValue(last);
            values_.pop_back();
            posInfo_.erase(key);
            if (_return) {
                _return->push_back(last);
            }
        }
    }

private:
    // 存储缓存的值的列表
    std::list<VALUE> values_;
    // 存储键到值列表中对应迭代器的映射
    std::unordered_map<KEY, typename std::list<VALUE>::iterator, HASH> posInfo_;
    // 存储被淘汰的值的向量
    std::vector<VALUE> elimiValues_;
    // 当前的淘汰策略
    EN_ELIMINATE_POLICY policy_;
    // 互斥锁，用于保证线程安全
    std::mutex mutex_;

    // 处理缓存已满时的淘汰操作
    void handleEviction() {
        const VALUE& val = values_.back();
        if (policy_ == EN_ELIMINATE_POLICY::EP_PENDING_DISPOSAL) {
            elimiValues_.push_back(val);
        }
        KEY lastkey = getKeyFromValue(val);
        values_.pop_back();
        posInfo_.erase(lastkey);
    }

    // 将对应的值移动到缓存列表头部，并更新键到迭代器的映射
    void moveToFront(const typename std::unordered_map<KEY, typename std::list<VALUE>::iterator, HASH>::iterator& it) {
        values_.splice(values_.begin(), values_, it->second);
        it->second = values_.begin();
    }

    // 根据值获取对应的键，需要在具体使用时根据 VALUE 类型实现此函数
    KEY getKeyFromValue(const VALUE& value) const {
        return value.get_key_from_val();
    }
};

#endif